home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Online / smbfs / source / proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-06-26  |  62.7 KB  |  2,606 lines

  1. /*
  2.  * $Id: proc.c,v 1.45 2001/06/26 11:29:40 olsen Exp $
  3.  *
  4.  * :ts=8
  5.  *
  6.  * proc.c
  7.  *
  8.  * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
  9.  *
  10.  * 28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per
  11.  *
  12.  * Modified for big endian support by Christian Starkjohann.
  13.  * Modified for use with AmigaOS by Olaf Barthel <olsen@sourcery.han.de>
  14.  */
  15.  
  16. #include "system_headers.h"
  17. #include "assert.h"
  18.  
  19. /*****************************************************************************/
  20.  
  21. #ifdef __SASC
  22. #define FAR __far
  23. #define ASM __asm
  24. #define REG(x) register __ ## x
  25. #define INLINE __inline
  26. #else
  27. #define FAR
  28. #define ASM
  29. #define REG(x)
  30. #define INLINE
  31. #endif /* __SASC */
  32.  
  33. /*****************************************************************************/
  34.  
  35. extern struct Library * DOSBase;
  36.  
  37. /*****************************************************************************/
  38.  
  39. extern LONG GetTimeZoneDelta(VOID);
  40. extern VOID ReportError(STRPTR fmt,...);
  41. extern VOID StringToUpper(STRPTR s);
  42. extern VOID LocalTime(time_t seconds,struct tm * tm);
  43. extern time_t MakeTime(const struct tm * const tm);
  44.  
  45. /*****************************************************************************/
  46.  
  47. extern void smb_encrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
  48. extern void smb_nt_encrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
  49.  
  50. /*****************************************************************************/
  51.  
  52. extern VOID FreeVecPooled(APTR address);
  53. extern APTR AllocVecPooled(ULONG size);
  54.  
  55. #define malloc(s) AllocVecPooled(s)
  56. #define free(m) FreeVecPooled(m)
  57.  
  58. /*****************************************************************************/
  59.  
  60. #include <smb/smbno.h>
  61. #include <smb/smb_fs.h>
  62.  
  63. /*****************************************************************************/
  64.  
  65. #define SMB_VWV(packet)    ((packet) + SMB_HEADER_LEN)
  66. #define SMB_CMD(packet)    ((packet)[8])
  67. #define SMB_WCT(packet)    ((packet)[SMB_HEADER_LEN - 1])
  68. #define SMB_BCC(packet)    smb_bcc(packet)
  69. #define SMB_BUF(packet)    ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
  70.  
  71. #define SMB_DIRINFO_SIZE 43
  72. #define SMB_STATUS_SIZE  21
  73.  
  74. /*****************************************************************************/
  75.  
  76. static byte *INLINE smb_encode_word(byte *p, word data);
  77. static byte *INLINE smb_decode_word(byte *p, word *data);
  78. static int INLINE utc2local(int time);
  79. static int INLINE local2utc(int time);
  80. static word INLINE smb_bcc(byte *packet);
  81. static int INLINE smb_verify(byte *packet, int command, int wct, int bcc);
  82. static byte *smb_encode_dialect(byte *p, const byte *name, int len);
  83. static byte *smb_encode_ascii(byte *p, const byte *name, int len);
  84. static void smb_encode_vblock(byte *p, const byte *data, word len, int fs);
  85. static byte *smb_decode_data(byte *p, byte *data, word *data_len, int fs);
  86. static byte *smb_name_mangle(byte *p, const byte *name);
  87. static int date_dos2unix(unsigned short time, unsigned short date);
  88. static void date_unix2dos(int unix_date, unsigned short *time, unsigned short *date);
  89. static int INLINE smb_valid_packet(byte *packet);
  90. static int smb_errno(int errcls, int error);
  91. static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);
  92. static int smb_retry(struct smb_server *server);
  93. static int smb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc);
  94. static byte *smb_setup_header(struct smb_server *server, byte command, word wct, word bcc);
  95. static byte *smb_setup_header_exclusive(struct smb_server *server, byte command, word wct, word bcc);
  96. static int smb_proc_do_create(struct smb_server *server, const char *path, int len, struct smb_dirent *entry, word command);
  97. static char *smb_decode_dirent(char *p, struct smb_dirent *entry);
  98. static int smb_proc_readdir_short(struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry);
  99. static char *smb_decode_long_dirent(char *p, struct smb_dirent *finfo, int level);
  100. static int smb_proc_readdir_long(struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry);
  101. static int smb_proc_reconnect(struct smb_server *server);
  102. static void smb_printerr(int class, int num);
  103.  
  104. /*****************************************************************************/
  105.  
  106. /*****************************************************************************
  107.  *
  108.  *  Encoding/Decoding section
  109.  *
  110.  *****************************************************************************/
  111. static byte * INLINE
  112. smb_encode_word (byte * p, word data)
  113. {
  114.   p[0] = data & 0x00ffU;
  115.   p[1] = (data & 0xff00U) >> 8;
  116.   return &p[2];
  117. }
  118.  
  119. static byte * INLINE
  120. smb_decode_word (byte * p, word * data)
  121. {
  122.   (*data) = (word) p[0] | p[1] << 8;
  123.   return &p[2];
  124. }
  125.  
  126. byte *
  127. smb_encode_smb_length (byte * p, dword len)
  128. {
  129.   p[0] = p[1] = 0;
  130.   p[2] = (len & 0xFF00) >> 8;
  131.   p[3] = (len & 0xFF);
  132.  
  133.   if (len > 0xFFFF)
  134.     p[1] |= 0x01;
  135.  
  136.   return &p[4];
  137. }
  138.  
  139. static byte *
  140. smb_encode_dialect (byte * p, const byte * name, int len)
  141. {
  142.   (*p++) = 2;
  143.   strcpy (p, name);
  144.   return p + len + 1;
  145. }
  146.  
  147. static byte *
  148. smb_encode_ascii (byte * p, const byte * name, int len)
  149. {
  150.   (*p++) = 4;
  151.   strcpy (p, name);
  152.   return p + len + 1;
  153. }
  154.  
  155. static void
  156. smb_encode_vblock (byte * p, const byte * data, word len, int fs)
  157. {
  158.   (*p++) = 5;
  159.   p = smb_encode_word (p, len);
  160.   memcpy (p, data, len);
  161. }
  162.  
  163. static byte *
  164. smb_decode_data (byte * p, byte * data, word * data_len, int fs)
  165. {
  166.   word len;
  167.  
  168.   if (!((*p) == 1 || (*p) == 5))
  169.     LOG (("Warning! Data block not starting with 1 or 5\n"));
  170.  
  171.   len = WVAL (p, 1);
  172.   p += 3;
  173.  
  174.   memcpy (data, p, len);
  175.  
  176.   (*data_len) = len;
  177.  
  178.   return p + len;
  179. }
  180.  
  181. static byte *
  182. smb_name_mangle (byte * p, const byte * name)
  183. {
  184.   int len, pad = 0;
  185.  
  186.   len = strlen (name);
  187.  
  188.   if (len < 16)
  189.     pad = 16 - len;
  190.  
  191.   (*p++) = 2 * (len + pad);
  192.  
  193.   while ((*name) != '\0')
  194.   {
  195.     (*p++) = ((*name) >> 4) + 'A';
  196.     (*p++) = ((*name) & 0x0F) + 'A';
  197.     name++;
  198.   }
  199.  
  200.   while (pad-- > 0)
  201.   {
  202.     (*p++) = 'C';
  203.     (*p++) = 'A';
  204.   }
  205.  
  206.   (*p++) = '\0';
  207.  
  208.   return p;
  209. }
  210.  
  211. static int INLINE
  212. utc2local (int time)
  213. {
  214.   int result;
  215.  
  216.   result = time - GetTimeZoneDelta();
  217.  
  218.   return result;
  219. }
  220.  
  221. static int INLINE
  222. local2utc (int time)
  223. {
  224.   int result;
  225.  
  226.   result = time + GetTimeZoneDelta();
  227.  
  228.   return result;
  229. }
  230.  
  231. /* Convert a MS-DOS time/date pair to a UNIX date (seconds since January 1st 1970). */
  232. static int
  233. date_dos2unix (unsigned short time, unsigned short date)
  234. {
  235.   time_t seconds;
  236.   struct tm tm;
  237.  
  238.   memset(&tm,0,sizeof(tm));
  239.  
  240.   tm.tm_sec  = 2 * (time & 0x1F);
  241.   tm.tm_min  = (time >> 5) & 0x3F;
  242.   tm.tm_hour = (time >> 11) & 0x1F;
  243.   tm.tm_mday = date & 0x1F;
  244.   tm.tm_mon  = ((date >> 5) & 0xF) - 1;
  245.   tm.tm_year = ((date >> 9) & 0x7F) + 80;
  246.  
  247.   seconds = MakeTime(&tm);
  248.  
  249.   return(seconds);
  250. }
  251.  
  252. /* Convert linear UNIX date to a MS-DOS time/date pair. */
  253. static void
  254. date_unix2dos (int unix_date, unsigned short *time, unsigned short *date)
  255. {
  256.   struct tm tm;
  257.  
  258.   LocalTime(unix_date,&tm);
  259.  
  260.   (*time) = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec / 2);
  261.   (*date) = ((tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday;
  262. }
  263.  
  264. /****************************************************************************
  265.  *
  266.  *  Support section.
  267.  *
  268.  ****************************************************************************/
  269. dword
  270. smb_len (byte * packet)
  271. {
  272.   return (dword)( ((packet[1] & 0x1) << 16L) | (packet[2] << 8L) | (packet[3]) );
  273. }
  274.  
  275. static word INLINE
  276. smb_bcc (byte * packet)
  277. {
  278.   int pos = SMB_HEADER_LEN + SMB_WCT (packet) * sizeof (word);
  279.  
  280.   return (word)(packet[pos] | packet[pos + 1] << 8);
  281. }
  282.  
  283. /* smb_valid_packet: We check if packet fulfills the basic
  284.    requirements of a smb packet
  285.  */
  286. static int INLINE
  287. smb_valid_packet (byte * packet)
  288. {
  289.   int result;
  290.  
  291.   LOG (("len: %ld, wct: %ld, bcc: %ld\n", smb_len (packet), SMB_WCT (packet), SMB_BCC (packet)));
  292.  
  293.   result = (packet[4] == 0xff
  294.          && packet[5] == 'S'
  295.          && packet[6] == 'M'
  296.          && packet[7] == 'B'
  297.          && (smb_len (packet) + 4 ==
  298.              SMB_HEADER_LEN + SMB_WCT (packet) * 2 + SMB_BCC (packet) + 2)) ? 0 : (-EIO);
  299.  
  300.  
  301.   return result;
  302. }
  303.  
  304. /* smb_verify: We check if we got the answer we expected, and if we
  305.    got enough data. If bcc == -1, we don't care.
  306.  */
  307. static int INLINE
  308. smb_verify (byte * packet, int command, int wct, int bcc)
  309. {
  310.   return (SMB_CMD (packet) == command &&
  311.           SMB_WCT (packet) >= wct &&
  312.           (bcc == -1 || SMB_BCC (packet) >= bcc)) ? 0 : -EIO;
  313. }
  314.  
  315. static int
  316. smb_errno (int errcls, int error)
  317. {
  318.   int result,i;
  319.  
  320.   if (errcls)
  321.     smb_printerr (errcls, error);
  322.  
  323.   if (errcls == ERRDOS)
  324.   {
  325.     static const int map[][2] =
  326.     {
  327.       ERRbadfunc,EINVAL,
  328.       ERRbadfile,ENOENT,
  329.       ERRbadpath,ENOENT,
  330.       ERRnofids,EMFILE,
  331.       ERRnoaccess,EACCES,
  332.       ERRbadfid,EBADF,
  333.       ERRbadmcb,EIO,
  334.       ERRnomem,ENOMEM,
  335.       ERRbadmem,EFAULT,
  336.       ERRbadenv,EIO,
  337.       ERRbadformat,EIO,
  338.       ERRbadaccess,EACCES,
  339.       ERRbaddata,E2BIG,
  340.       ERRbaddrive,ENXIO,
  341.       ERRremcd,EIO,
  342.       ERRdiffdevice,EXDEV,
  343.       ERRnofiles,0,
  344.       ERRbadshare,ETXTBSY,
  345.       ERRlock,EDEADLK,
  346.       ERRfilexists,EEXIST,
  347.       87,0,/* Unknown error! */
  348.       183,EEXIST,/* This next error seems to occur on an mv when
  349.                   * the destination exists
  350.                   */
  351.       -1
  352.     };
  353.  
  354.     result = EIO;
  355.  
  356.     for(i = 0 ; map[i][0] != -1 ; i++)
  357.     {
  358.       if(map[i][0] == error)
  359.       {
  360.         result = map[i][1];
  361.         break;
  362.       }
  363.     }
  364.   }
  365.   else if (errcls == ERRSRV)
  366.   {
  367.     static const int map[][2] =
  368.     {
  369.       ERRerror,ENFILE,
  370.       ERRbadpw,EINVAL,
  371.       ERRbadtype,EIO,
  372.       ERRaccess,EACCES,
  373.       -1
  374.     };
  375.  
  376.     result = EIO;
  377.  
  378.     for(i = 0 ; map[i][0] != -1 ; i++)
  379.     {
  380.       if(map[i][0] == error)
  381.       {
  382.         result = map[i][1];
  383.         break;
  384.       }
  385.     }
  386.   }
  387.   else if (errcls == ERRHRD)
  388.   {
  389.     static const int map[][2] =
  390.     {
  391.       ERRnowrite,EROFS,
  392.       ERRbadunit,ENODEV,
  393.       ERRnotready,EBUSY,
  394.       ERRbadcmd,EIO,
  395.       ERRdata,EIO,
  396.       ERRbadreq,ERANGE,
  397.       ERRbadshare,ETXTBSY,
  398.       ERRlock,EDEADLK,
  399.       -1
  400.     };
  401.  
  402.     result = EIO;
  403.  
  404.     for(i = 0 ; map[i][0] != -1 ; i++)
  405.     {
  406.       if(map[i][0] == error)
  407.       {
  408.         result = map[i][1];
  409.         break;
  410.       }
  411.     }
  412.   }
  413.   else if (errcls == ERRCMD)
  414.   {
  415.     result = EIO;
  416.   }
  417.   else
  418.   {
  419.     result = 0;
  420.   }
  421.  
  422.   return(result);
  423. }
  424.  
  425. #if DEBUG
  426.  
  427. static char
  428. print_char (char c)
  429. {
  430.   if ((c < ' ') || (c > '~'))
  431.     return '.';
  432.  
  433.   return c;
  434. }
  435.  
  436. static void
  437. smb_dump_packet (byte * packet)
  438. {
  439.   int i, j, len;
  440.   int errcls, error;
  441.  
  442.   errcls = (int) packet[9];
  443.   error = (int) (int) (packet[11] | packet[12] << 8);
  444.  
  445.   LOG (("smb_len = %ld  valid = %ld    \n", len = smb_len (packet), smb_valid_packet (packet)));
  446.   LOG (("smb_cmd = %ld  smb_wct = %ld  smb_bcc = %ld\n", packet[8], SMB_WCT (packet), SMB_BCC (packet)));
  447.   LOG (("smb_rcls = %ld smb_err = %ld\n", errcls, error));
  448.  
  449.   if (errcls)
  450.     smb_printerr (errcls, error);
  451.  
  452.   if (len > 100)
  453.     len = 100;
  454.  
  455.   PRINTHEADER();
  456.  
  457.   for (i = 0; i < len; i += 10)
  458.   {
  459.     PRINTF (("%03ld:", i));
  460.  
  461.     for (j = i; j < i + 10; j++)
  462.     {
  463.       if (j < len)
  464.         PRINTF (("%02lx ", packet[j]));
  465.       else
  466.         PRINTF (("   "));
  467.     }
  468.  
  469.     PRINTF ((": "));
  470.  
  471.     for (j = i; j < i + 10; j++)
  472.     {
  473.       if (j < len)
  474.         PRINTF (("%lc", print_char (packet[j])));
  475.     }
  476.  
  477.     PRINTF (("\n"));
  478.   }
  479. }
  480.  
  481. #endif /* DEBUG */
  482.  
  483. #if 0
  484. static void
  485. smb_lock_server (struct smb_server *server)
  486. {
  487.   server->lock = 1;
  488. }
  489.  
  490. static void
  491. smb_unlock_server (struct smb_server *server)
  492. {
  493.   if (server->lock != 1)
  494.     LOG (("smb_unlock_server: was not locked!\n"));
  495.  
  496.   server->lock = 0;
  497. }
  498. #else
  499.  
  500. #define smb_lock_server(s) ((void)0)
  501. #define smb_unlock_server(s) ((void)0)
  502.  
  503. #endif
  504.  
  505. /* smb_request_ok: We expect the server to be locked. Then we do the
  506.    request and check the answer completely. When smb_request_ok
  507.    returns 0, you can be quite sure that everything went well. When
  508.    the answer is <=0, the returned number is a valid unix errno.
  509.  */
  510. static int
  511. smb_request_ok (struct smb_server *s, int command, int wct, int bcc)
  512. {
  513.   int result;
  514.   int error;
  515.  
  516.   s->rcls = 0;
  517.   s->err = 0;
  518.  
  519.   result = smb_request (s);
  520.   if (result < 0)
  521.   {
  522.     LOG (("smb_request failed\n"));
  523.   }
  524.   else if ((error = smb_valid_packet (s->packet)) != 0)
  525.   {
  526.     LOG (("not a valid packet!\n"));
  527.     result = error;
  528.   }
  529.   else if (s->rcls != 0)
  530.   {
  531.     result = -smb_errno (s->rcls, s->err);
  532.   }
  533.   else if ((error = smb_verify (s->packet, command, wct, bcc)) != 0)
  534.   {
  535.     LOG (("smb_verify failed\n"));
  536.     result = error;
  537.   }
  538.  
  539.   return(result);
  540. }
  541.  
  542. /* smb_retry: This function should be called when smb_request_ok has
  543.    indicated an error. If the error was indicated because the
  544.    connection was killed, we try to reconnect. If smb_retry returns 0,
  545.    the error was indicated for another reason, so a retry would not be
  546.    of any use.
  547.  */
  548. static int
  549. smb_retry (struct smb_server *server)
  550. {
  551.   int result = 0;
  552.  
  553.   if (server->state == CONN_VALID)
  554.     goto out;
  555.  
  556.   if (smb_release (server) < 0)
  557.   {
  558.     LOG (("smb_retry: smb_release failed\n"));
  559.     server->state = CONN_RETRIED;
  560.     goto out;
  561.   }
  562.  
  563.   if (smb_proc_reconnect (server) < 0)
  564.   {
  565.     LOG (("smb_proc_reconnect failed\n"));
  566.     server->state = CONN_RETRIED;
  567.     goto out;
  568.   }
  569.  
  570.   server->state = CONN_VALID;
  571.   result = 1;
  572.  
  573.  out:
  574.  
  575.   return result;
  576. }
  577.  
  578. static int
  579. smb_request_ok_unlock (struct smb_server *s, int command, int wct, int bcc)
  580. {
  581.   int result;
  582.  
  583.   result = smb_request_ok (s, command, wct, bcc);
  584.  
  585.   smb_unlock_server (s);
  586.  
  587.   return result;
  588. }
  589.  
  590. /* smb_setup_header: We completely set up the packet. You only have to
  591.    insert the command-specific fields
  592.  */
  593. static byte *
  594. smb_setup_header (struct smb_server *server, byte command, word wct, word bcc)
  595. {
  596.   dword xmit_len = SMB_HEADER_LEN + wct * sizeof (word) + bcc + 2;
  597.   byte *p = server->packet;
  598.   byte *buf = server->packet;
  599.  
  600.   p = smb_encode_smb_length (p, xmit_len);
  601.  
  602.   BSET (p, 0, 0xff);
  603.   BSET (p, 1, 'S');
  604.   BSET (p, 2, 'M');
  605.   BSET (p, 3, 'B');
  606.   BSET (p, 4, command);
  607.  
  608.   p += 5;
  609.   memset (p, '\0', 19);
  610.   p += 19;
  611.   p += 8;
  612.  
  613.   WSET (buf, smb_tid, server->tid);
  614.   WSET (buf, smb_pid, 0); /* server->pid */
  615.   WSET (buf, smb_uid, server->server_uid);
  616.   WSET (buf, smb_mid, 0); /* server->mid */
  617.  
  618.   if (server->protocol > PROTOCOL_CORE)
  619.   {
  620.     BSET (buf, smb_flg, 0x8);
  621.     WSET (buf, smb_flg2, 0x3);
  622.   }
  623.  
  624.   (*p++) = wct; /* wct */
  625.   p += 2 * wct;
  626.   WSET (p, 0, bcc);
  627.  
  628.   return p + 2;
  629. }
  630.  
  631. /* smb_setup_header_exclusive waits on server->lock and locks the
  632.    server, when it's free. You have to unlock it manually when you're
  633.    finished with server->packet!
  634.  */
  635. static byte *
  636. smb_setup_header_exclusive (struct smb_server *server, byte command, word wct, word bcc)
  637. {
  638.   byte * result;
  639.  
  640.   smb_lock_server (server);
  641.  
  642.   result = smb_setup_header (server, command, wct, bcc);
  643.  
  644.   return result;
  645. }
  646.  
  647. /*****************************************************************************
  648.  *
  649.  *  File operation section.
  650.  *
  651.  ****************************************************************************/
  652. int
  653. smb_proc_open (struct smb_server *server, const char *pathname, int len, struct smb_dirent *entry)
  654. {
  655.   int error;
  656.   char *p;
  657.   char *buf = server->packet;
  658.   const word o_attr = aSYSTEM | aHIDDEN | aDIR;
  659.  
  660.   LOG (("path=%s\n", pathname));
  661.  
  662.   smb_lock_server (server);
  663.  
  664.  retry:
  665.   p = smb_setup_header (server, SMBopen, 2, 2 + len);
  666.   WSET (buf, smb_vwv0, 0x42); /* read/write */
  667.   WSET (buf, smb_vwv1, o_attr);
  668.   smb_encode_ascii (p, pathname, len);
  669.  
  670.   if ((error = smb_request_ok (server, SMBopen, 7, 0)) < 0)
  671.   {
  672.     if (smb_retry (server))
  673.       goto retry;
  674.  
  675.     if (error != -EACCES)
  676.       goto out;
  677.  
  678.     p = smb_setup_header (server, SMBopen, 2, 2 + len);
  679.     WSET (buf, smb_vwv0, 0x40); /* read only */
  680.     WSET (buf, smb_vwv1, o_attr);
  681.     smb_encode_ascii (p, pathname, len);
  682.  
  683.     if ((error = smb_request_ok (server, SMBopen, 7, 0)) < 0)
  684.     {
  685.       if (smb_retry (server))
  686.         goto retry;
  687.  
  688.       goto out;
  689.     }
  690.   }
  691.  
  692.   /* We should now have data in vwv[0..6]. */
  693.   entry->fileid = WVAL (buf, smb_vwv0);
  694.   entry->attr = WVAL (buf, smb_vwv1);
  695.   entry->ctime = entry->atime = entry->mtime = local2utc (DVAL (buf, smb_vwv2));
  696.   entry->size = DVAL (buf, smb_vwv4);
  697.   entry->opened = 1;
  698.  
  699.  out:
  700.  
  701.   smb_unlock_server (server);
  702.  
  703.   return error;
  704. }
  705.  
  706. /* smb_proc_close: in finfo->mtime we can send a modification time to
  707.    the server
  708.  */
  709. int
  710. smb_proc_close (struct smb_server *server, word fileid, dword mtime)
  711. {
  712.   char *buf = server->packet;
  713.   int local_time;
  714.   int result;
  715.  
  716.   if(mtime != 0 && mtime != 0xffffffff)
  717.   {
  718.     /* 0 and 0xffffffff mean: do not set mtime */
  719.     local_time = utc2local (mtime);
  720.   }
  721.   else
  722.   {
  723.     local_time = mtime;
  724.   }
  725.  
  726.   smb_setup_header_exclusive (server, SMBclose, 3, 0);
  727.   WSET (buf, smb_vwv0, fileid);
  728.   DSET (buf, smb_vwv1, local_time);
  729.  
  730.   result = smb_request_ok_unlock (server, SMBclose, 0, 0);
  731.  
  732.   return result;
  733. }
  734.  
  735. /* In smb_proc_read and smb_proc_write we do not retry, because the
  736.    file-id would not be valid after a reconnection.
  737.  */
  738.  
  739. /* smb_proc_read: fs indicates if it should be copied with
  740.    memcpy_tofs.
  741.  */
  742. int
  743. smb_proc_read (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int fs)
  744. {
  745.   word returned_count, data_len;
  746.   char *buf = server->packet;
  747.   int result;
  748.   int error;
  749.  
  750.   smb_setup_header_exclusive (server, SMBread, 5, 0);
  751.  
  752.   WSET (buf, smb_vwv0, finfo->fileid);
  753.   WSET (buf, smb_vwv1, count);
  754.   DSET (buf, smb_vwv2, offset);
  755.   WSET (buf, smb_vwv4, 0);
  756.  
  757.   if ((error = smb_request_ok (server, SMBread, 5, -1)) < 0)
  758.   {
  759.     result = error;
  760.     goto out;
  761.   }
  762.  
  763.   returned_count = WVAL (buf, smb_vwv0);
  764.  
  765.   smb_decode_data (SMB_BUF (server->packet), data, &data_len, fs);
  766.  
  767.   if (returned_count != data_len)
  768.   {
  769.     LOG (("Warning, returned_count != data_len\n"));
  770.     LOG (("ret_c=%ld, data_len=%ld\n", returned_count, data_len));
  771.   }
  772.   else
  773.   {
  774.     LOG (("ret_c=%ld, data_len=%ld\n", returned_count, data_len));
  775.   }
  776.  
  777.   result = data_len;
  778.  
  779.  out:
  780.  
  781.   smb_unlock_server (server);
  782.  
  783.   return result;
  784. }
  785.  
  786. /* count must be <= 65535. No error number is returned.  A result of 0
  787.    indicates an error, which has to be investigated by a normal read
  788.    call.
  789.  */
  790. int
  791. smb_proc_read_raw (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data)
  792. {
  793.   char *buf = server->packet;
  794.   int result;
  795.  
  796.   smb_setup_header_exclusive (server, SMBreadbraw, 8, 0);
  797.  
  798.   WSET (buf, smb_vwv0, finfo->fileid);
  799.   DSET (buf, smb_vwv1, offset);
  800.   WSET (buf, smb_vwv3, count);
  801.   WSET (buf, smb_vwv4, 0);
  802.   DSET (buf, smb_vwv5, 0);
  803.  
  804.   result = smb_request_read_raw (server, data, count);
  805.  
  806.   smb_unlock_server (server);
  807.  
  808.   return result;
  809. }
  810.  
  811. int
  812. smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offset, int count, const char *data)
  813. {
  814.   int res;
  815.   char *buf = server->packet;
  816.   byte *p;
  817.  
  818.   p = smb_setup_header_exclusive (server, SMBwrite, 5, count + 3);
  819.   WSET (buf, smb_vwv0, finfo->fileid);
  820.   WSET (buf, smb_vwv1, count);
  821.   DSET (buf, smb_vwv2, offset);
  822.   WSET (buf, smb_vwv4, 0);
  823.  
  824.   (*p++) = 1;
  825.   WSET (p, 0, count);
  826.   memcpy (p + 2, data, count);
  827.  
  828.   if ((res = smb_request_ok (server, SMBwrite, 1, 0)) >= 0)
  829.     res = WVAL (buf, smb_vwv0);
  830.  
  831.   smb_unlock_server (server);
  832.  
  833.   return res;
  834. }
  835.  
  836. /* count must be <= 65535 */
  837. int
  838. smb_proc_write_raw (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data)
  839. {
  840.   char *buf = server->packet;
  841.   int result;
  842.  
  843.   smb_setup_header_exclusive (server, SMBwritebraw, 11, 0);
  844.  
  845.   WSET (buf, smb_vwv0, finfo->fileid);
  846.   WSET (buf, smb_vwv1, count);
  847.   WSET (buf, smb_vwv2, 0);      /* reserved */
  848.   DSET (buf, smb_vwv3, offset);
  849.   DSET (buf, smb_vwv5, 0);      /* timeout */
  850.   WSET (buf, smb_vwv7, 1);      /* send final result response */
  851.   DSET (buf, smb_vwv8, 0);      /* reserved */
  852.   WSET (buf, smb_vwv10, 0);     /* no data in this buf */
  853.   WSET (buf, smb_vwv11, 0);     /* no data in this buf */
  854.  
  855.   result = smb_request_ok (server, SMBwritebraw, 1, 0);
  856.  
  857.   LOG (("first request returned %ld\n", result));
  858.  
  859.   if (result < 0)
  860.     goto out;
  861.  
  862.   result = smb_request_write_raw (server, data, count);
  863.  
  864.   LOG(("raw request returned %ld\n", result));
  865.  
  866.   if (result > 0)
  867.   {
  868.     int error;
  869.  
  870.     /* We have to do the checks of smb_request_ok here as well */
  871.     if ((error = smb_valid_packet (server->packet)) != 0)
  872.     {
  873.       LOG (("not a valid packet!\n"));
  874.       result = error;
  875.     }
  876.     else if (server->rcls != 0)
  877.     {
  878.       result = -smb_errno (server->rcls, server->err);
  879.     }
  880.     else if ((error = smb_verify (server->packet, SMBwritec, 1, 0)) != 0)
  881.     {
  882.       LOG (("smb_verify failed\n"));
  883.       result = error;
  884.     }
  885.   }
  886.  
  887.  out:
  888.  
  889.   smb_unlock_server (server);
  890.  
  891.   return result;
  892. }
  893.  
  894. /* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
  895. static int
  896. smb_proc_do_create (struct smb_server *server, const char *path, int len, struct smb_dirent *entry, word command)
  897. {
  898.   int error;
  899.   char *p;
  900.   char *buf = server->packet;
  901.   int local_time;
  902.  
  903.   smb_lock_server (server);
  904.  retry:
  905.   p = smb_setup_header (server, command, 3, len + 2);
  906.   WSET (buf, smb_vwv0, entry->attr);
  907.   local_time = utc2local (entry->ctime);
  908.   DSET (buf, smb_vwv1, local_time);
  909.   smb_encode_ascii (p, path, len);
  910.  
  911.   if ((error = smb_request_ok (server, command, 1, 0)) < 0)
  912.   {
  913.     if (smb_retry (server))
  914.       goto retry;
  915.  
  916.     smb_unlock_server (server);
  917.     goto out;
  918.   }
  919.  
  920.   entry->opened = 1;
  921.   entry->fileid = WVAL (buf, smb_vwv0);
  922.   smb_unlock_server (server);
  923.  
  924.   smb_proc_close (server, entry->fileid, entry->mtime);
  925.  
  926.  out:
  927.  
  928.   return error;
  929. }
  930.  
  931. int
  932. smb_proc_create (struct smb_server *server, const char *path, int len, struct smb_dirent *entry)
  933. {
  934.   return smb_proc_do_create (server, path, len, entry, SMBcreate);
  935. }
  936.  
  937. int
  938. smb_proc_mv (struct smb_server *server, const char *opath, const int olen, const char *npath, const int nlen)
  939. {
  940.   char *p;
  941.   char *buf = server->packet;
  942.   int result;
  943.  
  944.   smb_lock_server (server);
  945.  
  946.  retry:
  947.   p = smb_setup_header (server, SMBmv, 1, olen + nlen + 4);
  948.   WSET (buf, smb_vwv0, 0);
  949.  
  950.   p = smb_encode_ascii (p, opath, olen);
  951.   smb_encode_ascii (p, npath, olen);
  952.  
  953.   if ((result = smb_request_ok (server, SMBmv, 0, 0)) < 0)
  954.   {
  955.     if (smb_retry (server))
  956.       goto retry;
  957.   }
  958.  
  959.   smb_unlock_server (server);
  960.  
  961.   return result;
  962. }
  963.  
  964. int
  965. smb_proc_mkdir (struct smb_server *server, const char *path, const int len)
  966. {
  967.   char *p;
  968.   int result;
  969.  
  970.   smb_lock_server (server);
  971.  
  972.  retry:
  973.   p = smb_setup_header (server, SMBmkdir, 0, 2 + len);
  974.   smb_encode_ascii (p, path, len);
  975.  
  976.   if ((result = smb_request_ok (server, SMBmkdir, 0, 0)) < 0)
  977.   {
  978.     if (smb_retry (server))
  979.       goto retry;
  980.   }
  981.  
  982.   smb_unlock_server (server);
  983.  
  984.   return result;
  985. }
  986.  
  987. int
  988. smb_proc_rmdir (struct smb_server *server, const char *path, const int len)
  989. {
  990.   char *p;
  991.   int result;
  992.  
  993.   smb_lock_server (server);
  994.  
  995.  retry:
  996.   p = smb_setup_header (server, SMBrmdir, 0, 2 + len);
  997.   smb_encode_ascii (p, path, len);
  998.  
  999.   if ((result = smb_request_ok (server, SMBrmdir, 0, 0)) < 0)
  1000.   {
  1001.     if (smb_retry (server))
  1002.       goto retry;
  1003.   }
  1004.  
  1005.   smb_unlock_server (server);
  1006.  
  1007.   return result;
  1008. }
  1009.  
  1010. int
  1011. smb_proc_unlink (struct smb_server *server, const char *path, const int len)
  1012. {
  1013.   char *p;
  1014.   char *buf = server->packet;
  1015.   int result;
  1016.  
  1017.   smb_lock_server (server);
  1018.  
  1019.  retry:
  1020.   p = smb_setup_header (server, SMBunlink, 1, 2 + len);
  1021.   WSET (buf, smb_vwv0, 0);
  1022.   smb_encode_ascii (p, path, len);
  1023.  
  1024.   if ((result = smb_request_ok (server, SMBunlink, 0, 0)) < 0)
  1025.   {
  1026.     if (smb_retry (server))
  1027.       goto retry;
  1028.   }
  1029.  
  1030.   smb_unlock_server (server);
  1031.  
  1032.   return result;
  1033. }
  1034.  
  1035. int
  1036. smb_proc_trunc (struct smb_server *server, word fid, dword length)
  1037. {
  1038.   char *p;
  1039.   char *buf = server->packet;
  1040.   int result;
  1041.  
  1042.   smb_lock_server (server);
  1043.  
  1044.   p = smb_setup_header (server, SMBwrite, 5, 3);
  1045.   WSET (buf, smb_vwv0, fid);
  1046.   WSET (buf, smb_vwv1, 0);
  1047.   DSET (buf, smb_vwv2, length);
  1048.   WSET (buf, smb_vwv4, 0);
  1049.   smb_encode_ascii (p, "", 0);
  1050.  
  1051.   result = smb_request_ok (server, SMBwrite, 1, 0);
  1052.  
  1053.   smb_unlock_server (server);
  1054.  
  1055.   return result;
  1056. }
  1057.  
  1058. static char *
  1059. smb_decode_dirent (char *p, struct smb_dirent *entry)
  1060. {
  1061.   p += SMB_STATUS_SIZE; /* reserved (search_status) */
  1062.   entry->attr = BVAL (p, 0);
  1063.   entry->mtime = entry->atime = entry->ctime = date_dos2unix (WVAL (p, 1), WVAL (p, 3));
  1064.   entry->size = DVAL (p, 5);
  1065.   memcpy (entry->complete_path, p + 9, 13);
  1066.   LOG (("smb_decode_dirent: path = %s\n", entry->complete_path));
  1067.  
  1068.   return p + 22;
  1069. }
  1070.  
  1071. /* This routine is used to read in directory entries from the network.
  1072.    Note that it is for short directory name seeks, i.e.: protocol <
  1073.    PROTOCOL_LANMAN2
  1074.  */
  1075. static int
  1076. smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry)
  1077. {
  1078.   char *p;
  1079.   char *buf;
  1080.   int error;
  1081.   int result = 0;
  1082.   int i;
  1083.   int first, total_count;
  1084.   struct smb_dirent *current_entry;
  1085.   word bcc;
  1086.   word count;
  1087.   char status[SMB_STATUS_SIZE];
  1088.   int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE;
  1089.   int dirlen = strlen (path);
  1090.   char * mask;
  1091.  
  1092.   mask = malloc(dirlen + 5);
  1093.   if (mask == NULL)
  1094.   {
  1095.      result = (-ENOMEM);
  1096.      goto out;
  1097.   }
  1098.  
  1099.   strcpy (mask, path);
  1100.   strcat (mask, "\\*.*");
  1101.  
  1102.   LOG (("SMB call  readdir %ld @ %ld\n", cache_size, fpos));
  1103.   LOG (("          mask = %s\n", mask));
  1104.  
  1105.   buf = server->packet;
  1106.  
  1107.   smb_lock_server (server);
  1108.  
  1109.  retry:
  1110.   first = 1;
  1111.   total_count = 0;
  1112.   current_entry = entry;
  1113.  
  1114.   while (1)
  1115.   {
  1116.     if (first == 1)
  1117.     {
  1118.       p = smb_setup_header (server, SMBsearch, 2, 5 + strlen (mask));
  1119.       WSET (buf, smb_vwv0, entries_asked);
  1120.       WSET (buf, smb_vwv1, aDIR);
  1121.       p = smb_encode_ascii (p, mask, strlen (mask));
  1122.       (*p++) = 5;
  1123.       (void) smb_encode_word (p, 0);
  1124.     }
  1125.     else
  1126.     {
  1127.       p = smb_setup_header (server, SMBsearch, 2, 5 + SMB_STATUS_SIZE);
  1128.       WSET (buf, smb_vwv0, entries_asked);
  1129.       WSET (buf, smb_vwv1, aDIR);
  1130.       p = smb_encode_ascii (p, "", 0);
  1131.       (void) smb_encode_vblock (p, status, SMB_STATUS_SIZE, 0);
  1132.     }
  1133.  
  1134.     if ((error = smb_request_ok (server, SMBsearch, 1, -1)) < 0)
  1135.     {
  1136.       if ((server->rcls == ERRDOS) && (server->err == ERRnofiles))
  1137.       {
  1138.         result = total_count - fpos;
  1139.         goto unlock_return;
  1140.       }
  1141.       else
  1142.       {
  1143.         if (smb_retry (server))
  1144.           goto retry;
  1145.  
  1146.         result = error;
  1147.         goto unlock_return;
  1148.       }
  1149.     }
  1150.  
  1151.     p = SMB_VWV (server->packet);
  1152.     p = smb_decode_word (p, &count); /* vwv[0] = count-returned */
  1153.     p = smb_decode_word (p, &bcc);
  1154.  
  1155.     first = 0;
  1156.  
  1157.     if (count <= 0)
  1158.     {
  1159.       result = total_count - fpos;
  1160.       goto unlock_return;
  1161.     }
  1162.  
  1163.     if (bcc != count * SMB_DIRINFO_SIZE + 3)
  1164.     {
  1165.       result = -EIO;
  1166.       goto unlock_return;
  1167.     }
  1168.  
  1169.     p += 3; /* Skipping VBLOCK header (5, length lo, length hi). */
  1170.  
  1171.     /* Read the last entry into the status field. */
  1172.     memcpy (status, SMB_BUF (server->packet) + 3 + (count - 1) * SMB_DIRINFO_SIZE, SMB_STATUS_SIZE);
  1173.  
  1174.     /* Now we are ready to parse smb directory entries. */
  1175.  
  1176.     for (i = 0; i < count; i++)
  1177.     {
  1178.       if (total_count < fpos)
  1179.       {
  1180.         p += SMB_DIRINFO_SIZE;
  1181.         LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n", total_count, i, fpos));
  1182.       }
  1183.       else if (total_count >= fpos + cache_size)
  1184.       {
  1185.         result = total_count - fpos;
  1186.         goto unlock_return;
  1187.       }
  1188.       else
  1189.       {
  1190.         p = smb_decode_dirent (p, current_entry);
  1191.         current_entry += 1;
  1192.       }
  1193.  
  1194.       total_count += 1;
  1195.     }
  1196.   }
  1197.  
  1198.  unlock_return:
  1199.  
  1200.   if(mask != NULL)
  1201.     free(mask);
  1202.  
  1203.   smb_unlock_server (server);
  1204.  
  1205.  out:
  1206.  
  1207.   return result;
  1208. }
  1209.  
  1210. /*****************************************************************************/
  1211.  
  1212. #define MAX_DIGITS 4 /* NOTE: this is actually a hard-coded value (see below) */
  1213.  
  1214. /* Multiprecision arithmetics for beginners; we use 64 bits, chopped
  1215.  * into 16 bit pieces each. That allows us to comfortably execute all
  1216.  * calculations with 'long' arguments and not get into trouble because
  1217.  * of overflows and carry bits that don't exist. The assumption is that
  1218.  * the size of a 'long' is twice as large as that of a 'short'.
  1219.  */
  1220. struct digits
  1221. {
  1222.   unsigned short d[MAX_DIGITS];
  1223. };
  1224.  
  1225. /* Divide a multiprecision number by a positive integer. This is
  1226.  * essentially the division by a single "digit", as described in
  1227.  * Donald E. Knuth's "The Art of Computer Programming, Volume 2
  1228.  * Seminumerical Algorithms", 3rd edition, page 625 as the answer
  1229.  * to exercise 16 on page 282 in section 4.3.1. We don't really
  1230.  * need the more complex version since we just need to divide by
  1231.  * 10,000 and then by 1,000. The complex version is much more
  1232.  * complex than calling this division routine twice.
  1233.  */
  1234. static void
  1235. divide_by(struct digits * q,unsigned long div)
  1236. {
  1237.   int m;
  1238.  
  1239.   m = MAX_DIGITS;
  1240.   while(m > 0 && q->d[m-1] == 0)
  1241.     m--;
  1242.  
  1243.   if(m > 0)
  1244.   {
  1245.     unsigned long r,s;
  1246.     int j;
  1247.  
  1248.     r = 0;
  1249.     j = m - 1;
  1250.  
  1251.     do
  1252.     {
  1253.       r <<= 16;
  1254.  
  1255.       s = (r + q->d[j]);
  1256.  
  1257.       q->d[j] = s / div;
  1258.       r = s % div;
  1259.     }
  1260.     while(--j >= 0);
  1261.   }
  1262. }
  1263.  
  1264. /* This is an application of algorithm S ('Subtraction of
  1265.  * non-negative integers') described in Donald E. Knuth's
  1266.  * "The Art of Computer Programming, Volume 2 / Seminumerical
  1267.  * Algorithms", 3rd edition, page 267.
  1268.  */
  1269. static long
  1270. subtract_number(struct digits * u,unsigned long v)
  1271. {
  1272.   long d;
  1273.  
  1274.   /* This implementation takes advantage of the fact that
  1275.    * the 'width' of 'v' (64 bits) is just half the size of
  1276.    * 'u' (32 bits), which allows us to unroll the loop and
  1277.    * leave out some of the arguments which would not
  1278.    * contribute to the result anyway.
  1279.    */
  1280.  
  1281.   /* First round */
  1282.   d = ((long)u->d[0]) - (long)(v & 0xFFFF);
  1283.   u->d[0] = d;
  1284.  
  1285.   /* Second round */
  1286.   d = ((long)u->d[1]) - ((long)((v >> 16) & 0xFFFF)) - (d < 0);
  1287.   u->d[1] = d;
  1288.  
  1289.   /* Third round */
  1290.   d = ((long)u->d[2]) - (d < 0);
  1291.   u->d[2] = d;
  1292.  
  1293.   /* Fourth round */
  1294.   d = ((long)u->d[3]) - (d < 0);
  1295.   u->d[3] = d;
  1296.  
  1297.   return(d < 0);
  1298. }
  1299.  
  1300. /* Interpret an 8 byte "filetime" structure to a 'time_t'.
  1301.  * It's originally in "100ns units since jan 1st 1601".
  1302.  *
  1303.  * Unlike the Samba implementation of that date conversion
  1304.  * algorithm this one tries to perform the entire
  1305.  * calculation using integer operations only.
  1306.  */
  1307. static time_t
  1308. interpret_long_date(char * p)
  1309. {
  1310.   unsigned long hi,lo;
  1311.   struct digits d;
  1312.   time_t result;
  1313.   int i,k;
  1314.  
  1315.   /* Extract the 64 bit time value. */
  1316.   lo = DVAL(p,0);
  1317.   hi = DVAL(p,4);
  1318.  
  1319.   /* Chop the time into handy 16 bit chunks. */
  1320.   d.d[3] = hi >> 16;
  1321.   d.d[2] = hi & 0xFFFF;
  1322.   d.d[1] = lo >> 16;
  1323.   d.d[0] = lo & 0xFFFF;
  1324.  
  1325.   /* Divide by 10,000,000 in two easy pieces. */
  1326.   divide_by(&d,10000);
  1327.   divide_by(&d,1000);
  1328.  
  1329.   /* Adjust by 369 years (11,644,473,600 seconds). */
  1330.   k = 0;
  1331.   for(i = 0 ; k == 0 && i < 4 ; i++)
  1332.     k += subtract_number(&d,2911118400);
  1333.  
  1334.   /* If the result did not produce an underflow or overflow,
  1335.    * return the number of seconds encoded in the two least
  1336.    * significant 'digits'.
  1337.    */
  1338.   if(k == 0 && d.d[3] == 0 && d.d[2] == 0)
  1339.     result = (time_t)((((unsigned long)d.d[1]) << 16) + d.d[0]);
  1340.   else
  1341.     result = 0;
  1342.  
  1343.   return(result);
  1344. }
  1345.  
  1346. /*****************************************************************************/
  1347.  
  1348. static void
  1349. smb_get_dirent_name(char *p,int level,char ** name_ptr,int * len_ptr)
  1350. {
  1351.   switch (level)
  1352.   {
  1353.   case 1: /* OS/2 understands this */
  1354.     (*name_ptr) = p + 27;
  1355.     (*len_ptr) = strlen(p + 27);
  1356.     break;
  1357.  
  1358.   case 2: /* this is what OS/2 uses */
  1359.     (*name_ptr) = p + 31;
  1360.     (*len_ptr) = strlen(p + 31);
  1361.     break;
  1362.  
  1363.   case 260: /* NT uses this, but also accepts 2 */
  1364.     (*name_ptr) = p + 94;
  1365.     (*len_ptr) = min (DVAL (p+60, 0), SMB_MAXNAMELEN);
  1366.     break;
  1367.  
  1368.   default:
  1369.     (*name_ptr) = NULL;
  1370.     (*len_ptr) = 0;
  1371.     break;
  1372.   }
  1373. }
  1374.  
  1375. /* interpret a long filename structure - this is mostly guesses at the
  1376.    moment.  The length of the structure is returned.  The structure of
  1377.    a long filename depends on the info level. 260 is used by NT and 2
  1378.    is used by OS/2.
  1379.  */
  1380. static char *
  1381. smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level)
  1382. {
  1383.   char *result;
  1384.  
  1385.   switch (level)
  1386.   {
  1387.   case 1: /* OS/2 understands this */
  1388.  
  1389.     #if DEBUG
  1390.     {
  1391.       char buffer[255];
  1392.  
  1393.       memcpy(buffer,p + 27,sizeof(buffer)-1);
  1394.       buffer[sizeof(buffer)-1] = '\0';
  1395.  
  1396.       LOG(("type=%ld, name='%s'\n",level,buffer));
  1397.     }
  1398.     #endif /* DEBUG */
  1399.  
  1400.     if (finfo != NULL)
  1401.     {
  1402.       strcpy (finfo->complete_path, p + 27);
  1403.       finfo->len = strlen (finfo->complete_path);
  1404.       finfo->size = DVAL (p, 16);
  1405.       finfo->attr = BVAL (p, 24);
  1406.       finfo->ctime = date_dos2unix (WVAL (p, 6), WVAL (p, 4));
  1407.       finfo->atime = date_dos2unix (WVAL (p, 10), WVAL (p, 8));
  1408.       finfo->mtime = date_dos2unix (WVAL (p, 14), WVAL (p, 12));
  1409.     }
  1410.  
  1411.     result = p + 28 + BVAL (p, 26);
  1412.  
  1413.     break;
  1414.  
  1415.   case 2: /* this is what OS/2 uses */
  1416.  
  1417.     #if DEBUG
  1418.     {
  1419.       char buffer[255];
  1420.  
  1421.       memcpy(buffer,p + 31,sizeof(buffer)-1);
  1422.       buffer[sizeof(buffer)-1] = '\0';
  1423.  
  1424.       LOG(("type=%ld, name='%s'\n",level,buffer));
  1425.     }
  1426.     #endif /* DEBUG */
  1427.  
  1428.     if (finfo != NULL)
  1429.     {
  1430.       strcpy (finfo->complete_path, p + 31);
  1431.       finfo->len = strlen (finfo->complete_path);
  1432.       finfo->size = DVAL (p, 16);
  1433.       finfo->attr = BVAL (p, 24);
  1434.       finfo->ctime = date_dos2unix (WVAL (p, 6), WVAL (p, 4));
  1435.       finfo->atime = date_dos2unix (WVAL (p, 10), WVAL (p, 8));
  1436.       finfo->mtime = date_dos2unix (WVAL (p, 14), WVAL (p, 12));
  1437.     }
  1438.  
  1439.     result = p + 32 + BVAL (p, 30);
  1440.  
  1441.     break;
  1442.  
  1443.   case 260: /* NT uses this, but also accepts 2 */
  1444.  
  1445.     #if DEBUG
  1446.     {
  1447.       char buffer[255];
  1448.       int len;
  1449.  
  1450.       len = min (DVAL (p+60, 0), sizeof(buffer)-1);
  1451.  
  1452.       memcpy(buffer,p+94,len);
  1453.       buffer[len] = '\0';
  1454.  
  1455.       LOG(("type=%ld, name='%s'\n",level,buffer));
  1456.     }
  1457.     #endif /* DEBUG */
  1458.  
  1459.     result = p + WVAL (p, 0);
  1460.  
  1461.     if (finfo != NULL)
  1462.     {
  1463.       int namelen;
  1464.  
  1465.       p += 4;                   /* next entry offset */
  1466.       p += 4;                   /* fileindex */
  1467.       finfo->ctime = interpret_long_date(p);
  1468.       p += 8;
  1469.       finfo->atime = interpret_long_date(p);
  1470.       p += 8;
  1471.       p += 8;                   /* write time */
  1472.       finfo->mtime = interpret_long_date(p);
  1473.       p += 8;
  1474.       finfo->size = DVAL (p, 0);
  1475.       p += 8;
  1476.       p += 8;                   /* alloc size */
  1477.       finfo->attr = BVAL (p, 0);
  1478.       p += 4;
  1479.       namelen = min (DVAL (p, 0), SMB_MAXNAMELEN);
  1480.       p += 4;
  1481.       p += 4;                   /* EA size */
  1482.       p += 2;                   /* short name len? */
  1483.       p += 24;                  /* short name? */
  1484.       strncpy (finfo->complete_path, p, namelen);
  1485.       finfo->complete_path[namelen] = '\0';
  1486.       finfo->len = namelen;
  1487.     }
  1488.  
  1489.     break;
  1490.  
  1491.   default:
  1492.  
  1493.     if (finfo != NULL)
  1494.     {
  1495.       /* I have to set times to 0 here, because I do not
  1496.          have specs about this for all info levels.
  1497.        */
  1498.       finfo->ctime = finfo->mtime = finfo->atime = 0;
  1499.     }
  1500.  
  1501.     LOG (("Unknown long filename format %ld\n", level));
  1502.     result = p + WVAL (p, 0);
  1503.  
  1504.     break;
  1505.   }
  1506.  
  1507.   return result;
  1508. }
  1509.  
  1510. static int
  1511. smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry)
  1512. {
  1513.   int max_matches = 512; /* this should actually be based on the max_xmit value */
  1514.  
  1515.   /* NT uses 260, OS/2 uses 2. Both accept 1. */
  1516.   int info_level = server->protocol < PROTOCOL_NT1 ? 1 : 260;
  1517.  
  1518.   char *p;
  1519.   int i;
  1520.   int first;
  1521.   int total_count = 0;
  1522.   struct smb_dirent *current_entry;
  1523.  
  1524.   char *resp_data;
  1525.   char *resp_param;
  1526.   int resp_data_len = 0;
  1527.   int resp_param_len = 0;
  1528.  
  1529.   int attribute = aSYSTEM | aHIDDEN | aDIR;
  1530.   int result;
  1531.   int error = 0;
  1532.  
  1533.   int ff_searchcount;
  1534.   int ff_eos = 0;
  1535.   int ff_dir_handle = 0;
  1536.   int ff_resume_key = 0;
  1537.   int loop_count = 0;
  1538.  
  1539.   unsigned char *outbuf = server->packet;
  1540.  
  1541.   int dirlen = strlen (path) + 3;
  1542.   char *mask;
  1543.   int masklen;
  1544.  
  1545.   ENTER();
  1546.  
  1547.   /* ZZZ experimental 'max_matches' adjustment */
  1548.   /*
  1549.   if(info_level == 260)
  1550.     max_matches = server->max_xmit / 360;
  1551.   else
  1552.     max_matches = server->max_xmit / 40;
  1553.   */
  1554.  
  1555.   SHOWVALUE(server->max_xmit);
  1556.   SHOWVALUE(max_matches);
  1557.  
  1558.   mask = malloc (dirlen);
  1559.   if (mask == NULL)
  1560.   {
  1561.     LOG (("Memory allocation failed\n"));
  1562.     error = (-ENOMEM);
  1563.     SHOWVALUE(error);
  1564.     goto out;
  1565.   }
  1566.  
  1567.   strcpy (mask, path);
  1568.   strcat (mask, "\\*");
  1569.   masklen = strlen (mask);
  1570.  
  1571.   LOG (("SMB call lreaddir %ld @ %ld\n", cache_size, fpos));
  1572.   LOG (("          mask = %s\n", mask));
  1573.  
  1574.   resp_param = NULL;
  1575.   resp_data = NULL;
  1576.  
  1577.   smb_lock_server (server);
  1578.  
  1579.  retry:
  1580.  
  1581.   first = 1;
  1582.   total_count = 0;
  1583.   current_entry = entry;
  1584.  
  1585.   while (ff_eos == 0)
  1586.   {
  1587.     loop_count++;
  1588.     if (loop_count > 200)
  1589.     {
  1590.       LOG (("smb_proc_readdir_long: Looping in FIND_NEXT???\n"));
  1591.       error = -EIO;
  1592.       SHOWVALUE(error);
  1593.       break;
  1594.     }
  1595.  
  1596.     memset (outbuf, 0, 39);
  1597.     smb_setup_header (server, SMBtrans2, 15, 5 + 12 + masklen + 1);
  1598.  
  1599.     WSET (outbuf, smb_tpscnt, 12 + masklen + 1);
  1600.     WSET (outbuf, smb_tdscnt, 0);
  1601.     WSET (outbuf, smb_mprcnt, 10);
  1602.     WSET (outbuf, smb_mdrcnt, server->max_xmit);
  1603.     WSET (outbuf, smb_msrcnt, 0);
  1604.     WSET (outbuf, smb_flags, 0);
  1605.     DSET (outbuf, smb_timeout, 0);
  1606.     WSET (outbuf, smb_pscnt, WVAL (outbuf, smb_tpscnt));
  1607.     WSET (outbuf, smb_psoff, ((SMB_BUF (outbuf) + 3) - outbuf) - 4);
  1608.     WSET (outbuf, smb_dscnt, 0);
  1609.     WSET (outbuf, smb_dsoff, 0);
  1610.     WSET (outbuf, smb_suwcnt, 1);
  1611.     WSET (outbuf, smb_setup0, first == 1 ? TRANSACT2_FINDFIRST : TRANSACT2_FINDNEXT);
  1612.  
  1613.     p = SMB_BUF (outbuf);
  1614.     (*p++) = 0;   /* put in a null smb_name */
  1615.     (*p++) = 'D';
  1616.     (*p++) = ' '; /* this was added because OS/2 does it */
  1617.  
  1618.     if (first != 0)
  1619.     {
  1620.       LOG (("first match\n"));
  1621.       WSET (p, 0, attribute);   /* attribute */
  1622.       WSET (p, 2, max_matches); /* max count */
  1623.       WSET (p, 4, 8 + 4 + 2);   /* resume required + close on end + continue */
  1624.       WSET (p, 6, info_level);
  1625.       DSET (p, 8, 0);
  1626.     }
  1627.     else
  1628.     {
  1629.       LOG (("next match; ff_dir_handle=0x%lx ff_resume_key=%ld mask='%s'\n", ff_dir_handle, ff_resume_key, mask));
  1630.       WSET (p, 0, ff_dir_handle);
  1631.       WSET (p, 2, max_matches); /* max count */
  1632.       WSET (p, 4, info_level);
  1633.       DSET (p, 6, ff_resume_key);
  1634.       WSET (p, 10, 8 + 4 + 2);  /* resume required + close on end + continue */
  1635.     }
  1636.  
  1637.     p += 12;
  1638.  
  1639.     if(masklen > 0)
  1640.       memcpy (p, mask, masklen);
  1641.  
  1642.     p += masklen;
  1643.     (*p++) = 0;
  1644.     (*p) = 0;
  1645.  
  1646.     result = smb_trans2_request (server, &resp_data_len, &resp_param_len, &resp_data, &resp_param);
  1647.     LOG (("smb_proc_readdir_long: smb_trans2_request returns %ld\n", result));
  1648.  
  1649.     if (result < 0)
  1650.     {
  1651.       if (smb_retry (server))
  1652.         goto retry;
  1653.  
  1654.       LOG (("smb_proc_readdir_long: got error from trans2_request\n"));
  1655.       error = result;
  1656.       SHOWVALUE(error);
  1657.       break;
  1658.     }
  1659.  
  1660.     /* Apparently, there is a bug in Windows 95 and friends which
  1661.      * causes the directory read attempt to fail if you're asking
  1662.      * for too much data too fast...
  1663.      */
  1664.     if(server->rcls == ERRSRV && server->err == ERRerror)
  1665.     {
  1666.       SHOWMSG("ouch; delaying and retrying");
  1667.       Delay(TICKS_PER_SECOND / 5);
  1668.       continue;
  1669.     }
  1670.  
  1671.     if (server->rcls != 0)
  1672.     {
  1673.       LOG (("server->rcls = %ld err = %ld\n",server->rcls, server->err));
  1674.       error = smb_errno (server->rcls, server->err);
  1675.       SHOWVALUE(error);
  1676.       break;
  1677.     }
  1678.  
  1679.     /* parse out some important return info */
  1680.     p = resp_param;
  1681.     if (first != 0)
  1682.     {
  1683.       ff_dir_handle = WVAL (p, 0);
  1684.       ff_searchcount = WVAL (p, 2);
  1685.       ff_eos = WVAL (p, 4);
  1686.     }
  1687.     else
  1688.     {
  1689.       ff_searchcount = WVAL (p, 0);
  1690.       ff_eos = WVAL (p, 2);
  1691.     }
  1692.  
  1693.     LOG (("received %ld entries (eos=%ld)\n",ff_searchcount, ff_eos));
  1694.     if (ff_searchcount == 0)
  1695.       break;
  1696.  
  1697.     /* point to the data bytes */
  1698.     p = resp_data;
  1699.  
  1700.     /* Now we are ready to parse smb directory entries. */
  1701.     for (i = 0; i < ff_searchcount; i++)
  1702.     {
  1703.       if(i == ff_searchcount - 1)
  1704.       {
  1705.         char * last_name;
  1706.         int len;
  1707.  
  1708.         ff_resume_key = DVAL(p, 0);
  1709.  
  1710.         smb_get_dirent_name(p,info_level,&last_name,&len);
  1711.         if(len > 0)
  1712.         {
  1713.           #if DEBUG
  1714.           {
  1715.             char buffer[SMB_MAXNAMELEN+1];
  1716.  
  1717.             memcpy(buffer,last_name,len);
  1718.             buffer[len] = '\0';
  1719.  
  1720.             LOG(("last name = '%s'\n",buffer));
  1721.           }
  1722.           #endif /* DEBUG */
  1723.  
  1724.           if(len + 1 > dirlen)
  1725.           {
  1726.             D(("increasing mask; old value = %ld new value = %ld",dirlen,len+1));
  1727.  
  1728.             if(mask != NULL)
  1729.               free (mask);
  1730.  
  1731.             dirlen = len + 1;
  1732.             SHOWVALUE(dirlen);
  1733.  
  1734.             mask = malloc (dirlen);
  1735.             if (mask == NULL)
  1736.             {
  1737.               LOG (("smb_proc_readdir_long: Memory allocation failed\n"));
  1738.               error = -ENOMEM;
  1739.               SHOWVALUE(error);
  1740.               goto fail;
  1741.             }
  1742.           }
  1743.  
  1744.           memcpy (mask, last_name, len);
  1745.           mask[len] = '\0';
  1746.           masklen = len;
  1747.         }
  1748.         else
  1749.         {
  1750.           masklen = 0;
  1751.         }
  1752.       }
  1753.  
  1754.       if (total_count < fpos)
  1755.       {
  1756.         p = smb_decode_long_dirent (p, NULL, info_level);
  1757.         LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n",total_count, i, fpos));
  1758.       }
  1759.       else if (total_count >= fpos + cache_size)
  1760.       {
  1761.         p = smb_decode_long_dirent (p, NULL, info_level);
  1762.         LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n",total_count, i, fpos));
  1763.         continue;
  1764.       }
  1765.       else
  1766.       {
  1767.         p = smb_decode_long_dirent (p, current_entry, info_level);
  1768.         current_entry += 1;
  1769.       }
  1770.  
  1771.       total_count += 1;
  1772.     }
  1773.  
  1774.     SHOWVALUE(ff_resume_key);
  1775.  
  1776.     if (resp_data != NULL)
  1777.     {
  1778.       free (resp_data);
  1779.       resp_data = NULL;
  1780.     }
  1781.  
  1782.     if (resp_param != NULL)
  1783.     {
  1784.       free (resp_param);
  1785.       resp_param = NULL;
  1786.     }
  1787.  
  1788.     first = 0;
  1789.  
  1790.     if (ff_searchcount > 0)
  1791.       loop_count = 0;
  1792.   }
  1793.  
  1794.  fail:
  1795.  
  1796.   /* finished: not needed any more */
  1797.   if (mask != NULL)
  1798.     free (mask);
  1799.  
  1800.   if (resp_data != NULL)
  1801.     free (resp_data);
  1802.  
  1803.   if (resp_param != NULL)
  1804.     free (resp_param);
  1805.  
  1806.   smb_unlock_server (server);
  1807.  
  1808.  out:
  1809.  
  1810.   if(error < 0)
  1811.   {
  1812.     RETURN(error);
  1813.     return(error);
  1814.   }
  1815.   else
  1816.   {
  1817.     RETURN (total_count - fpos);
  1818.     return (total_count - fpos);
  1819.   }
  1820. }
  1821.  
  1822. int
  1823. smb_proc_readdir (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry)
  1824. {
  1825.   int result;
  1826.  
  1827.   if (server->protocol >= PROTOCOL_LANMAN2)
  1828.     result = smb_proc_readdir_long (server, path, fpos, cache_size, entry);
  1829.   else
  1830.     result = smb_proc_readdir_short (server, path, fpos, cache_size, entry);
  1831.  
  1832.   return result;
  1833. }
  1834.  
  1835. int
  1836. smb_proc_getattr_core (struct smb_server *server, const char *path, int len, struct smb_dirent *entry)
  1837. {
  1838.   int result;
  1839.   char *p;
  1840.   char *buf = server->packet;
  1841.  
  1842.   smb_lock_server (server);
  1843.  
  1844.   LOG (("smb_proc_getattr: %s\n", path));
  1845.  
  1846.  retry:
  1847.   p = smb_setup_header (server, SMBgetatr, 0, 2 + len);
  1848.   smb_encode_ascii (p, path, len);
  1849.  
  1850.   if ((result = smb_request_ok (server, SMBgetatr, 10, 0)) < 0)
  1851.   {
  1852.     if (smb_retry (server))
  1853.       goto retry;
  1854.  
  1855.     goto out;
  1856.   }
  1857.  
  1858.   entry->attr = WVAL (buf, smb_vwv0);
  1859.  
  1860.   /* The server only tells us 1 time */
  1861.   entry->ctime = entry->atime = entry->mtime = local2utc (DVAL (buf, smb_vwv1));
  1862.  
  1863.   entry->size = DVAL (buf, smb_vwv3);
  1864.  
  1865.  out:
  1866.  
  1867.   smb_unlock_server (server);
  1868.  
  1869.   return result;
  1870. }
  1871.  
  1872. /* smb_proc_getattrE: entry->fid must be valid */
  1873.  
  1874. int
  1875. smb_proc_getattrE (struct smb_server *server, struct smb_dirent *entry)
  1876. {
  1877.   char *buf = server->packet;
  1878.   int result;
  1879.  
  1880.   smb_setup_header_exclusive (server, SMBgetattrE, 1, 0);
  1881.   WSET (buf, smb_vwv0, entry->fileid);
  1882.  
  1883.   if ((result = smb_request_ok (server, SMBgetattrE, 11, 0)) < 0)
  1884.     goto out;
  1885.  
  1886.   entry->ctime = date_dos2unix (WVAL (buf, smb_vwv1), WVAL (buf, smb_vwv0));
  1887.   entry->atime = date_dos2unix (WVAL (buf, smb_vwv3), WVAL (buf, smb_vwv2));
  1888.   entry->mtime = date_dos2unix (WVAL (buf, smb_vwv5), WVAL (buf, smb_vwv4));
  1889.   entry->size = DVAL (buf, smb_vwv6);
  1890.   entry->attr = WVAL (buf, smb_vwv10);
  1891.  
  1892.  out:
  1893.  
  1894.   smb_unlock_server (server);
  1895.  
  1896.   return result;
  1897. }
  1898.  
  1899. /* In core protocol, there is only 1 time to be set, we use
  1900.    entry->mtime, to make touch work.
  1901.  */
  1902. int
  1903. smb_proc_setattr_core (struct smb_server *server, const char *path, int len, struct smb_dirent *new_finfo)
  1904. {
  1905.   char *p;
  1906.   char *buf = server->packet;
  1907.   int result;
  1908.   int local_time;
  1909.  
  1910.   smb_lock_server (server);
  1911.  
  1912.  retry:
  1913.   LOG (("smb_proc_setattr_core\n"));
  1914.   p = smb_setup_header (server, SMBsetatr, 8, 4 + len);
  1915.   WSET (buf, smb_vwv0, new_finfo->attr);
  1916.   local_time = utc2local (new_finfo->mtime);
  1917.   DSET (buf, smb_vwv1, local_time);
  1918.   p = smb_encode_ascii (p, path, len);
  1919.   (void) smb_encode_ascii (p, "", 0);
  1920.  
  1921.   if ((result = smb_request_ok (server, SMBsetatr, 0, 0)) < 0)
  1922.   {
  1923.     if (smb_retry (server))
  1924.       goto retry;
  1925.   }
  1926.  
  1927.   smb_unlock_server (server);
  1928.  
  1929.   return result;
  1930. }
  1931.  
  1932. /* smb_proc_setattrE: we do not retry here, because we rely on fid,
  1933.    which would not be valid after a retry.
  1934.  */
  1935. int
  1936. smb_proc_setattrE (struct smb_server *server, word fid, struct smb_dirent *new_entry)
  1937. {
  1938.   char *buf = server->packet;
  1939.   word date, time;
  1940.   int result;
  1941.  
  1942.   LOG (("smb_proc_setattrE\n"));
  1943.   smb_setup_header_exclusive (server, SMBsetattrE, 7, 0);
  1944.  
  1945.   WSET (buf, smb_vwv0, fid);
  1946.  
  1947.   date_unix2dos (new_entry->ctime, &time, &date);
  1948.   WSET (buf, smb_vwv1, date);
  1949.   WSET (buf, smb_vwv2, time);
  1950.  
  1951.   date_unix2dos (new_entry->atime, &time, &date);
  1952.   WSET (buf, smb_vwv3, date);
  1953.   WSET (buf, smb_vwv4, time);
  1954.  
  1955.   date_unix2dos (new_entry->mtime, &time, &date);
  1956.   WSET (buf, smb_vwv5, date);
  1957.   WSET (buf, smb_vwv6, time);
  1958.  
  1959.   result = smb_request_ok_unlock (server, SMBsetattrE, 0, 0);
  1960.  
  1961.   return result;
  1962. }
  1963.  
  1964. int
  1965. smb_proc_dskattr (struct smb_server *server, struct smb_dskattr *attr)
  1966. {
  1967.   int error;
  1968.   char *p;
  1969.  
  1970.   smb_lock_server (server);
  1971.  
  1972.  retry:
  1973.   smb_setup_header (server, SMBdskattr, 0, 0);
  1974.  
  1975.   if ((error = smb_request_ok (server, SMBdskattr, 5, 0)) < 0)
  1976.   {
  1977.     if (smb_retry (server))
  1978.       goto retry;
  1979.  
  1980.     goto out;
  1981.   }
  1982.  
  1983.   p = SMB_VWV (server->packet);
  1984.   p = smb_decode_word (p, &attr->total);
  1985.   p = smb_decode_word (p, &attr->allocblocks);
  1986.   p = smb_decode_word (p, &attr->blocksize);
  1987.   (void) smb_decode_word (p, &attr->free);
  1988.  
  1989.  out:
  1990.  
  1991.   smb_unlock_server (server);
  1992.  
  1993.   return error;
  1994. }
  1995.  
  1996. /*****************************************************************************
  1997.  *
  1998.  *  Mount/umount operations.
  1999.  *
  2000.  ****************************************************************************/
  2001. struct smb_prots
  2002. {
  2003.   enum smb_protocol prot;
  2004.   const char *name;
  2005. };
  2006.  
  2007. /* smb_proc_reconnect: We expect the server to be locked, so that you
  2008.    can call the routine from within smb_retry. The socket must be
  2009.    created, like after a user-level socket()-call. It may not be
  2010.    connected.
  2011.  */
  2012. static int
  2013. smb_proc_reconnect (struct smb_server *server)
  2014. {
  2015.   static const struct smb_prots prots[] =
  2016.   {
  2017.     {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
  2018.     {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
  2019.     {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
  2020.     {PROTOCOL_LANMAN1, "LANMAN1.0"},
  2021.     {PROTOCOL_LANMAN2, "LM1.2X002"},
  2022.     {PROTOCOL_NT1, "NT LM 0.12"},
  2023.     {PROTOCOL_NT1, "NT LANMAN 1.0"},
  2024.  
  2025.     {-1, NULL}
  2026.   };
  2027.  
  2028.   char dev[] = "A:";
  2029.   int i, plength;
  2030.   int max_xmit = 1024; /* Space needed for first request. */
  2031.   int given_max_xmit = server->mount_data.max_xmit;
  2032.   int result;
  2033.   word any_word;
  2034.   byte *p;
  2035.   unsigned char password[24];
  2036.   int password_len;
  2037.   unsigned char nt_password[24];
  2038.   int nt_password_len;
  2039.   unsigned char full_share[100];
  2040.   int full_share_len;
  2041.   byte *packet;
  2042.  
  2043.   if (server->max_recv <= 0)
  2044.     server->max_recv = given_max_xmit > 8000 ? given_max_xmit : 8000;
  2045.  
  2046.   if ((result = smb_connect (server)) < 0)
  2047.   {
  2048.     LOG (("smb_proc_reconnect: could not smb_connect\n"));
  2049.     goto fail;
  2050.   }
  2051.  
  2052.   /* Here we assume that the connection is valid */
  2053.   server->state = CONN_VALID;
  2054.  
  2055.   if (server->packet != NULL)
  2056.     free (server->packet);
  2057.  
  2058.   server->packet = malloc (server->max_recv);
  2059.   if (server->packet == NULL)
  2060.   {
  2061.     LOG (("smb_proc_connect: No memory! Bailing out.\n"));
  2062.     result = -ENOMEM;
  2063.     goto fail;
  2064.   }
  2065.  
  2066.   packet = server->packet;
  2067.  
  2068.   server->max_xmit = max_xmit;
  2069.  
  2070.   /*
  2071.    * Start with an RFC1002 session request packet.
  2072.    */
  2073.   p = packet + 4;
  2074.  
  2075.   p = smb_name_mangle (p, server->mount_data.server_name);
  2076.   p = smb_name_mangle (p, server->mount_data.client_name);
  2077.  
  2078.   smb_encode_smb_length (packet, (byte *) p - (byte *) (packet));
  2079.  
  2080.   packet[0] = 0x81; /* SESSION REQUEST */
  2081.  
  2082.   if ((result = smb_request (server)) < 0)
  2083.   {
  2084.     LOG (("smb_proc_connect: Failed to send SESSION REQUEST.\n"));
  2085.     goto fail;
  2086.   }
  2087.  
  2088.   if (packet[0] != 0x82)
  2089.   {
  2090.     LOG (("smb_proc_connect: Did not receive positive response (err = %lx)\n",packet[0]));
  2091.  
  2092.     #if DEBUG
  2093.     {
  2094.       smb_dump_packet (packet);
  2095.     }
  2096.     #endif /* DEBUG */
  2097.  
  2098.     result = -EIO;
  2099.     goto fail;
  2100.   }
  2101.  
  2102.   LOG (("smb_proc_connect: Passed SESSION REQUEST.\n"));
  2103.  
  2104.   /* Now we are ready to send a SMB Negotiate Protocol packet. */
  2105.   memset (packet, 0, SMB_HEADER_LEN);
  2106.  
  2107.   plength = 0;
  2108.   for (i = 0; prots[i].name != NULL; i++)
  2109.     plength += strlen (prots[i].name) + 2;
  2110.  
  2111.   smb_setup_header (server, SMBnegprot, 0, plength);
  2112.  
  2113.   p = SMB_BUF (packet);
  2114.  
  2115.   for (i = 0; prots[i].name != NULL; i++)
  2116.     p = smb_encode_dialect (p, prots[i].name, strlen (prots[i].name));
  2117.  
  2118.   LOG (("smb_proc_connect: Request SMBnegprot...\n"));
  2119.   if ((result = smb_request_ok (server, SMBnegprot, 1, -1)) < 0)
  2120.   {
  2121.     LOG (("smb_proc_connect: Failure requesting SMBnegprot\n"));
  2122.     goto fail;
  2123.   }
  2124.  
  2125.   LOG (("Verified!\n"));
  2126.  
  2127.   p = SMB_VWV (packet);
  2128.   p = smb_decode_word (p, &any_word);
  2129.   i = any_word;
  2130.  
  2131.   server->protocol = prots[i].prot;
  2132.  
  2133.   LOG (("smb_proc_connect: Server wants %s protocol.\n",prots[i].name));
  2134.  
  2135.   if (server->protocol > PROTOCOL_LANMAN1)
  2136.   {
  2137.     int user_len = strlen (server->mount_data.username)+1;
  2138.  
  2139.     LOG (("smb_proc_connect: password = %s\n",server->mount_data.password));
  2140.     LOG (("smb_proc_connect: usernam = %s\n",server->mount_data.username));
  2141.     LOG (("smb_proc_connect: blkmode = %ld\n",WVAL (packet, smb_vwv5)));
  2142.  
  2143.     if (server->protocol >= PROTOCOL_NT1)
  2144.     {
  2145.       server->maxxmt = DVAL (packet, smb_vwv3 + 1);
  2146.       server->blkmode = DVAL (packet, smb_vwv9 + 1);
  2147.       server->sesskey = DVAL (packet, smb_vwv7 + 1);
  2148.  
  2149.       server->security_mode = BVAL(packet, smb_vwv1);
  2150.       memcpy(server->crypt_key,SMB_BUF(packet),8);
  2151.     }
  2152.     else
  2153.     {
  2154.       server->maxxmt = WVAL (packet, smb_vwv2);
  2155.       server->blkmode = WVAL (packet, smb_vwv5);
  2156.       server->sesskey = DVAL (packet, smb_vwv6);
  2157.  
  2158.       server->security_mode = BVAL(packet, smb_vwv1);
  2159.       memcpy(server->crypt_key,SMB_BUF(packet),8);
  2160.     }
  2161.  
  2162.     SHOWVALUE(server->security_mode);
  2163.  
  2164.     if(server->security_mode & 2)
  2165.     {
  2166.       int i;
  2167.  
  2168.       SHOWMSG("encrypted passwords required");
  2169.  
  2170.       memset(password,0,sizeof(password));
  2171.       strncpy(password,server->mount_data.password,sizeof(password)-1);
  2172.  
  2173.       smb_encrypt(password,server->crypt_key,password);
  2174.       password_len = 24;
  2175.  
  2176.       PRINTHEADER();
  2177.       PRINTF(("password: "));
  2178.       for(i = 0 ; i < 24 ; i++)
  2179.         PRINTF(("%02lx ",password[i]));
  2180.       PRINTF(("\n"));
  2181.  
  2182.       memset(nt_password,0,sizeof(nt_password));
  2183.       strncpy(nt_password,server->mount_data.password,sizeof(nt_password)-1);
  2184.  
  2185.       smb_nt_encrypt(nt_password,server->crypt_key,nt_password);
  2186.       nt_password_len = 24;
  2187.  
  2188.       PRINTHEADER();
  2189.       PRINTF(("nt_password: "));
  2190.       for(i = 0 ; i < 24 ; i++)
  2191.         PRINTF(("%02lx ",nt_password[i]));
  2192.       PRINTF(("\n"));
  2193.  
  2194.       PRINTHEADER();
  2195.       PRINTF(("crypt_key: "));
  2196.       for(i = 0 ; i < 8 ; i++)
  2197.         PRINTF(("%02lx ",server->crypt_key[i]));
  2198.       PRINTF(("\n"));
  2199.     }
  2200.     else
  2201.     {
  2202.       SHOWMSG("plain text passwords sufficient");
  2203.  
  2204.       password_len = strlen(server->mount_data.password)+1;
  2205.       nt_password_len = 0;
  2206.     }
  2207.  
  2208.     /* If in share level security then don't send a password now */
  2209.     if((server->security_mode & 1) == 0)
  2210.     {
  2211.       SHOWMSG("share level security; zapping passwords");
  2212.       strcpy(password,"");
  2213.       password_len = 0;
  2214.  
  2215.       strcpy(nt_password,"");
  2216.       nt_password_len = 0;
  2217.     }
  2218.  
  2219.     SHOWVALUE(password_len);
  2220.     SHOWVALUE(nt_password_len);
  2221.  
  2222.     LOG (("smb_proc_connect: workgroup = %s\n", server->mount_data.workgroup_name));
  2223.     if (server->protocol >= PROTOCOL_NT1)
  2224.     {
  2225.       char *OS_id = "AmigaOS";
  2226.       char *client_id = "smbfs";
  2227.  
  2228.       SHOWMSG("server->protocol >= PROTOCOL_NT1");
  2229.  
  2230.       smb_setup_header (server, SMBsesssetupX, 13, user_len + password_len + nt_password_len + strlen (server->mount_data.workgroup_name)+1 + strlen (OS_id)+1 + strlen (client_id)+1);
  2231.  
  2232.       WSET (packet, smb_vwv0, 0xff);
  2233.       WSET (packet, smb_vwv2, given_max_xmit);
  2234.       WSET (packet, smb_vwv3, 2);
  2235.       WSET (packet, smb_vwv4, 0); /* server->pid */
  2236.       DSET (packet, smb_vwv5, server->sesskey);
  2237.       WSET (packet, smb_vwv7, password_len);
  2238.       WSET (packet, smb_vwv8, nt_password_len);
  2239.  
  2240.       p = SMB_BUF (packet);
  2241.  
  2242.       if(nt_password_len != 0)
  2243.       {
  2244.         SHOWMSG("adding encrypted passwords");
  2245.  
  2246.         memcpy (p, password, password_len);
  2247.         p += password_len;
  2248.  
  2249.         memcpy (p, nt_password, nt_password_len);
  2250.         p += nt_password_len;
  2251.       }
  2252.       else
  2253.       {
  2254.         SHOWMSG("adding plain text password");
  2255.  
  2256.         memcpy (p, server->mount_data.password, password_len);
  2257.         p += password_len;
  2258.       }
  2259.  
  2260.       memcpy (p, server->mount_data.username, user_len);
  2261.       p += user_len;
  2262.  
  2263.       strcpy (p, server->mount_data.workgroup_name);
  2264.       p += strlen (p) + 1;
  2265.  
  2266.       strcpy (p, OS_id);
  2267.       p += strlen (p) + 1;
  2268.  
  2269.       strcpy (p, client_id);
  2270.     }
  2271.     else
  2272.     {
  2273.       smb_setup_header (server, SMBsesssetupX, 10,
  2274.                         user_len + password_len);
  2275.  
  2276.       WSET (packet, smb_vwv0, 0xff);
  2277.       WSET (packet, smb_vwv1, 0);
  2278.       WSET (packet, smb_vwv2, given_max_xmit);
  2279.       WSET (packet, smb_vwv3, 2);
  2280.       WSET (packet, smb_vwv4, 0); /* server->pid */
  2281.       DSET (packet, smb_vwv5, server->sesskey);
  2282.       WSET (packet, smb_vwv7, password_len);
  2283.       WSET (packet, smb_vwv8, 0);
  2284.       WSET (packet, smb_vwv9, 0);
  2285.  
  2286.       p = SMB_BUF (packet);
  2287.       memcpy (p, server->mount_data.password, password_len);
  2288.       p += password_len;
  2289.       memcpy (p, server->mount_data.username, user_len);
  2290.     }
  2291.  
  2292.     if ((result = smb_request_ok (server, SMBsesssetupX, 3, 0)) < 0)
  2293.     {
  2294.       LOG (("smb_proc_connect: SMBsessetupX failed\n"));
  2295.       goto fail;
  2296.     }
  2297.  
  2298.     smb_decode_word (packet + 32, &(server->server_uid));
  2299.   }
  2300.   else
  2301.   {
  2302.     server->maxxmt = 0;
  2303.     server->blkmode = 0;
  2304.     server->sesskey = 0;
  2305.  
  2306.     password_len = strlen(server->mount_data.password)+1;
  2307.     nt_password_len = 0;
  2308.   }
  2309.  
  2310.   if(nt_password_len != 0)
  2311.   {
  2312.     strcpy(full_share,"//");
  2313.     strcat(full_share,server->mount_data.server_name);
  2314.     strcat(full_share,"/");
  2315.     strcat(full_share,server->mount_data.service);
  2316.  
  2317.     full_share_len = strlen(full_share);
  2318.  
  2319.     for(i = 0 ; i < full_share_len ; i++)
  2320.     {
  2321.       if(full_share[i] == '/')
  2322.         full_share[i] = '\\';
  2323.     }
  2324.  
  2325.     StringToUpper(full_share);
  2326.  
  2327.     SHOWSTRING(full_share);
  2328.  
  2329.     memset (packet, 0, SMB_HEADER_LEN);
  2330.  
  2331.     smb_setup_header (server, SMBtconX, 4, password_len + full_share_len+1 + strlen(dev)+1);
  2332.  
  2333.     WSET (packet, smb_vwv0, 0xFF);
  2334.     WSET (packet, smb_vwv3, password_len);
  2335.  
  2336.     p = SMB_BUF (packet);
  2337.  
  2338.     if(nt_password_len > 0)
  2339.       memcpy(p,password,password_len);
  2340.     else
  2341.       memcpy (p, server->mount_data.password, password_len);
  2342.  
  2343.     p += password_len;
  2344.  
  2345.     memcpy(p,full_share,full_share_len+1);
  2346.     p += full_share_len+1;
  2347.  
  2348.     strcpy(p,dev);
  2349.  
  2350.     BSET(packet,smb_rcls,1);
  2351.  
  2352.     if ((result = smb_request_ok (server, SMBtconX, 3, 0)) < 0)
  2353.     {
  2354.       SHOWVALUE(SMB_WCT(packet));
  2355.  
  2356.       LOG (("smb_proc_connect: SMBtconX not verified.\n"));
  2357.       goto fail;
  2358.     }
  2359.  
  2360.     SHOWVALUE(SMB_WCT(packet));
  2361.  
  2362.     server->tid = WVAL(packet,smb_tid);
  2363.   }
  2364.   else
  2365.   {
  2366.     /* Fine! We have a connection, send a tcon message. */
  2367.     smb_setup_header (server, SMBtcon, 0, 6 + strlen (server->mount_data.service) + strlen (server->mount_data.password) + strlen (dev));
  2368.  
  2369.     p = SMB_BUF (packet);
  2370.     p = smb_encode_ascii (p, server->mount_data.service, strlen (server->mount_data.service));
  2371.     p = smb_encode_ascii (p, server->mount_data.password, strlen (server->mount_data.password));
  2372.     (void) smb_encode_ascii (p, dev, strlen (dev));
  2373.  
  2374.     if ((result = smb_request_ok (server, SMBtcon, 2, 0)) < 0)
  2375.     {
  2376.       LOG (("smb_proc_connect: SMBtcon not verified.\n"));
  2377.       goto fail;
  2378.     }
  2379.  
  2380.     LOG (("OK! Managed to set up SMBtcon!\n"));
  2381.  
  2382.     p = SMB_VWV (packet);
  2383.     p = smb_decode_word (p, &server->max_xmit);
  2384.  
  2385.     SHOWVALUE(server->max_xmit);
  2386.  
  2387.     if (server->max_xmit > given_max_xmit)
  2388.       server->max_xmit = given_max_xmit;
  2389.  
  2390.     /* Added by Brian Willette - We were ignoring the server's initial
  2391.      * maxbuf value
  2392.      */
  2393.     if (server->maxxmt != 0 && server->max_xmit > server->maxxmt)
  2394.       server->max_xmit = server->maxxmt;
  2395.  
  2396.     SHOWVALUE(server->max_xmit);
  2397.  
  2398.     (void) smb_decode_word (p, &server->tid);
  2399.   }
  2400.  
  2401.   /* Ok, everything is fine. max_xmit does not include */
  2402.   /* the TCP-SMB header of 4 bytes. */
  2403.   if (server->max_xmit < 65535 - 4)
  2404.     server->max_xmit += 4;
  2405.  
  2406.   LOG (("max_xmit = %ld, tid = %ld\n", server->max_xmit, server->tid));
  2407.  
  2408.   LOG (("smb_proc_connect: Normal exit\n"));
  2409.  
  2410.   return 0;
  2411.  
  2412.  fail:
  2413.  
  2414.   server->state = CONN_INVALID;
  2415.  
  2416.   return result;
  2417. }
  2418.  
  2419. /* smb_proc_reconnect: server->packet is allocated with
  2420.    server->max_xmit bytes if and only if we return >= 0
  2421.  */
  2422. int
  2423. smb_proc_connect (struct smb_server *server)
  2424. {
  2425.   int result;
  2426.   smb_lock_server (server);
  2427.  
  2428.   result = smb_proc_reconnect (server);
  2429.  
  2430.   if ((result < 0) && (server->packet != NULL))
  2431.   {
  2432.     free (server->packet);
  2433.     server->packet = NULL;
  2434.   }
  2435.  
  2436.   smb_unlock_server (server);
  2437.  
  2438.   return result;
  2439. }
  2440.  
  2441. /* error code stuff - put together by Merik Karman
  2442.    merik@blackadder.dsh.oz.au
  2443.  */
  2444. typedef struct
  2445. {
  2446.   char *name;
  2447.   int code;
  2448.   char *message;
  2449. } err_code_struct;
  2450.  
  2451. /* Dos Error Messages */
  2452. static const err_code_struct dos_msgs[] =
  2453. {
  2454.   {"ERRbadfunc", 1, "Invalid function"},
  2455.   {"ERRbadfile", 2, "File not found"},
  2456.   {"ERRbadpath", 3, "Directory invalid"},
  2457.   {"ERRnofids", 4, "No file descriptors available"},
  2458.   {"ERRnoaccess", 5, "Access denied"},
  2459.   {"ERRbadfid", 6, "Invalid file handle"},
  2460.   {"ERRbadmcb", 7, "Memory control blocks destroyed"},
  2461.   {"ERRnomem", 8, "Insufficient server memory to perform the requested function"},
  2462.   {"ERRbadmem", 9, "Invalid memory block address"},
  2463.   {"ERRbadenv", 10, "Invalid environment"},
  2464.   {"ERRbadformat", 11, "Invalid format"},
  2465.   {"ERRbadaccess", 12, "Invalid open mode"},
  2466.   {"ERRbaddata", 13, "Invalid data"},
  2467.   {"ERR", 14, "reserved"},
  2468.   {"ERRbaddrive", 15, "Invalid drive specified"},
  2469.   {"ERRremcd", 16, "A Delete Directory request attempted  to  remove  the  server's  current directory"},
  2470.   {"ERRdiffdevice", 17, "Not same device"},
  2471.   {"ERRnofiles", 18, "A File Search command can find no more files matching the specified criteria"},
  2472.   {"ERRbadshare", 32, "The sharing mode specified for an Open conflicts with existing  FIDs  on the file"},
  2473.   {"ERRlock", 33, "A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process"},
  2474.   {"ERRfilexists", 80, "The file named in a Create Directory, Make  New  File  or  Link  request already exists"},
  2475.   {"ERRbadpipe", 230, "Pipe invalid"},
  2476.   {"ERRpipebusy", 231, "All instances of the requested pipe are busy"},
  2477.   {"ERRpipeclosing", 232, "Pipe close in progress"},
  2478.   {"ERRnotconnected", 233, "No process on other end of pipe"},
  2479.   {"ERRmoredata", 234, "There is more data to be returned"},
  2480.  
  2481.   {NULL, -1, NULL}
  2482. };
  2483.  
  2484. /* Server Error Messages */
  2485. static const err_code_struct server_msgs[] =
  2486. {
  2487.   {"ERRerror", 1, "Non-specific error code"},
  2488.   {"ERRbadpw", 2, "Bad password - name/password pair in a Tree Connect or Session Setup are invalid"},
  2489.   {"ERRbadtype", 3, "reserved"},
  2490.   {"ERRaccess", 4, "The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID"},
  2491.   {"ERRinvnid", 5, "The tree ID (TID) specified in a command was invalid"},
  2492.   {"ERRinvnetname", 6, "Invalid network name in tree connect"},
  2493.   {"ERRinvdevice", 7, "Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection"},
  2494.   {"ERRqfull", 49, "Print queue full (files) -- returned by open print file"},
  2495.   {"ERRqtoobig", 50, "Print queue full -- no space"},
  2496.   {"ERRqeof", 51, "EOF on print queue dump"},
  2497.   {"ERRinvpfid", 52, "Invalid print file FID"},
  2498.   {"ERRsmbcmd", 64, "The server did not recognize the command received"},
  2499.   {"ERRsrverror", 65, "The server encountered an internal error, e.g., system file unavailable"},
  2500.   {"ERRfilespecs", 67, "The file handle (FID) and pathname parameters contained an invalid  combination of values"},
  2501.   {"ERRreserved", 68, "reserved"},
  2502.   {"ERRbadpermits", 69, "The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute"},
  2503.   {"ERRreserved", 70, "reserved"},
  2504.   {"ERRsetattrmode", 71, "The attribute mode in the Set File Attribute request is invalid"},
  2505.   {"ERRpaused", 81, "Server is paused"},
  2506.   {"ERRmsgoff", 82, "Not receiving messages"},
  2507.   {"ERRnoroom", 83, "No room to buffer message"},
  2508.   {"ERRrmuns", 87, "Too many remote user names"},
  2509.   {"ERRtimeout", 88, "Operation timed out"},
  2510.   {"ERRnoresource", 89, "No resources currently available for request"},
  2511.   {"ERRtoomanyuids", 90, "Too many UIDs active on this session"},
  2512.   {"ERRbaduid", 91, "The UID is not known as a valid ID on this session"},
  2513.   {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode"},
  2514.   {"ERRusestd", 251, "Temp unable to support Raw, use standard read/write"},
  2515.   {"ERRcontmpx", 252, "Continue in MPX mode"},
  2516.   {"ERRreserved", 253, "reserved"},
  2517.   {"ERRreserved", 254, "reserved"},
  2518.   {"ERRnosupport", 0xFFFF, "Function not supported"},
  2519.  
  2520.   {NULL, -1, NULL}
  2521. };
  2522.  
  2523. /* Hard Error Messages */
  2524. static const err_code_struct hard_msgs[] =
  2525. {
  2526.   {"ERRnowrite", 19, "Attempt to write on write-protected diskette"},
  2527.   {"ERRbadunit", 20, "Unknown unit"},
  2528.   {"ERRnotready", 21, "Drive not ready"},
  2529.   {"ERRbadcmd", 22, "Unknown command"},
  2530.   {"ERRdata", 23, "Data error (CRC)"},
  2531.   {"ERRbadreq", 24, "Bad request structure length"},
  2532.   {"ERRseek", 25, "Seek error"},
  2533.   {"ERRbadmedia", 26, "Unknown media type"},
  2534.   {"ERRbadsector", 27, "Sector not found"},
  2535.   {"ERRnopaper", 28, "Printer out of paper"},
  2536.   {"ERRwrite", 29, "Write fault"},
  2537.   {"ERRread", 30, "Read fault"},
  2538.   {"ERRgeneral", 31, "General failure"},
  2539.   {"ERRbadshare", 32, "A open conflicts with an existing open"},
  2540.   {"ERRlock", 33, "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process"},
  2541.   {"ERRwrongdisk", 34, "The wrong disk was found in a drive"},
  2542.   {"ERRFCBUnavail", 35, "No FCBs are available to process request"},
  2543.   {"ERRsharebufexc", 36, "A sharing buffer has been exceeded"},
  2544.  
  2545.   {NULL, -1, NULL}
  2546. };
  2547.  
  2548. typedef struct
  2549. {
  2550.   int code;
  2551.   char *class;
  2552.   err_code_struct *err_msgs;
  2553. } err_class_struct;
  2554.  
  2555. static const err_class_struct err_classes[] =
  2556. {
  2557.   { 0, "SUCCESS", NULL },
  2558.   { 0x01, "ERRDOS", dos_msgs },
  2559.   { 0x02, "ERRSRV", server_msgs },
  2560.   { 0x03, "ERRHRD", hard_msgs },
  2561.   { 0x04, "ERRXOS", NULL },
  2562.   { 0xE1, "ERRRMX1", NULL },
  2563.   { 0xE2, "ERRRMX2", NULL },
  2564.   { 0xE3, "ERRRMX3", NULL },
  2565.   { 0xFF, "ERRCMD", NULL },
  2566.  
  2567.   { -1, NULL, NULL }
  2568. };
  2569.  
  2570. static void
  2571. smb_printerr (int class, int num)
  2572. {
  2573.   int i, j;
  2574.   err_code_struct *err;
  2575.  
  2576.   for (i = 0; err_classes[i].class; i++)
  2577.   {
  2578.     if (err_classes[i].code != class)
  2579.       continue;
  2580.  
  2581.     if (!err_classes[i].err_msgs)
  2582.     {
  2583.       ReportError("%s - %ld.", err_classes[i].class, num);
  2584.  
  2585.       LOG (("%s - %ld\n", err_classes[i].class, num));
  2586.       return;
  2587.     }
  2588.  
  2589.     err = err_classes[i].err_msgs;
  2590.     for (j = 0; err[j].name; j++)
  2591.     {
  2592.       if (num != err[j].code)
  2593.         continue;
  2594.  
  2595.       ReportError ("%s - %s (%s).", err_classes[i].class, err[j].name, err[j].message);
  2596.  
  2597.       LOG (("%s - %s (%s)\n",err_classes[i].class, err[j].name,err[j].message));
  2598.       return;
  2599.     }
  2600.   }
  2601.  
  2602.   ReportError ("Unknown error - (%ld, %ld).", class, num);
  2603.  
  2604.   LOG (("Unknown error - (%ld, %ld)\n", class, num));
  2605. }
  2606.